import logging
import os
import re

from difflib import SequenceMatcher
from oecp.utils.shell import shell_cmd
from oecp.proxy.rpm_proxy import RPMProxy
from oecp.result.compare_result import CMP_RESULT_SAME, CompareResultComposite, CMP_TYPE_RPM, CMP_TYPE_RPM_JABI, \
    CompareResultComponent, CMP_RESULT_DIFF
from oecp.executor.base import CompareExecutor


logger = logging.getLogger('oecp')


class JABICompareExecutor(CompareExecutor):

    def __init__(self, dump_a, dump_b, config):
        super(JABICompareExecutor, self).__init__(dump_a, dump_b, config)
        self.dump_a = dump_a.run()
        self.dump_b = dump_b.run()
        cache_require_key = 'extract'
        self._work_dir = self.config.get(cache_require_key, {}).get('work_dir', '/tmp/oecp')
        self.data = 'data'
        self.split_flag = '__rpm__'

    @staticmethod
    def _split_common_jars(files_a, files_b):
        common_file_pairs = []
        for file_a in files_a:
            for file_b in files_b:
                # 相似度大于0.9，才认为是一对需要对比的jar包，有失误率
                file_name_a, file_name_b = os.path.basename(file_a), os.path.basename(file_b)
                ratio = SequenceMatcher(None, file_name_a, file_name_b).ratio()
                if ratio > 0.9:
                    if file_name_a.split('.')[0] == file_name_b.split('.')[0]:
                        common_file_pairs.append([file_a, file_b])
        return common_file_pairs

    def _compare_result(self, dump_a, dump_b, single_result=CMP_RESULT_SAME):

        kind = dump_a['kind']
        rpm_a, rpm_b = dump_a['rpm'], dump_b['rpm']
        result = CompareResultComposite(CMP_TYPE_RPM, single_result, rpm_a, rpm_b, dump_a['category'])
        dump_a_files, dump_b_files = dump_a[self.data], dump_b[self.data]
        common_file_pairs = self._split_common_jars(dump_a_files, dump_b_files)
        if not common_file_pairs:
            logger.debug(f"No jar package found, ignored with {dump_b['rpm']} and {dump_b['rpm']}")
            return result
        verbose_cmp_path = f'{rpm_a}__cmp__{rpm_b}'
        base_dir = os.path.join(self._work_dir, kind, verbose_cmp_path)
        if not os.path.exists(base_dir):
            os.makedirs(base_dir)
        for pair in common_file_pairs:
            base_a = os.path.basename(pair[0])
            base_b = os.path.basename(pair[1])
            path_prefix = f"{base_a.split('.')[0]}_cmp_{base_b.split('.')[0]}"
            file_path = os.path.join(base_dir, f'{path_prefix}__compat_report.html')
            cmd = "japi-compliance-checker -bin -lib common {} {} -report-path {}".format(pair[0], pair[1], file_path)
            ret, out, err = shell_cmd(cmd.split())

            if not ret and out:
                match = re.search(r'Binary compatibility: (.+)\s', out)
                if match:
                    compat_result = match.groups()[0]
                    data = CompareResultComponent(
                        CMP_TYPE_RPM_JABI, compat_result, base_a, base_b, file_path)
                    if compat_result != '100%':
                        result.set_cmp_result(CMP_RESULT_DIFF)
                    result.add_component(data)
        return result

    def compare(self):
        result_list = []
        for dump_a in self.dump_a:
            for dump_b in self.dump_b:
                # 取rpm name 相同进行比较
                if RPMProxy.rpm_name(dump_a['rpm']) == RPMProxy.rpm_name(dump_b['rpm']):
                    result = self._compare_result(dump_a, dump_b)
                    result_list.append(result)
        return result_list

    def run(self):
        result = self.compare()
        return result
